@file:JvmName("PermissionResultLauncher")

package com.wquick.base.utils.permissionFlow.utils

import androidx.activity.ComponentActivity
import androidx.activity.result.ActivityResultCallback
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.ActivityResultRegistry
import androidx.fragment.app.Fragment
import com.wquick.base.utils.permissionFlow.PermissionFlow
import com.wquick.base.utils.permissionFlow.contract.RequestPermissionsContract

/**
 * Returns a [ActivityResultLauncher] for this Activity which internally notifies [PermissionFlow]
 * about the state change whenever permission state is changed with this launcher.
 *
 * Usage:
 * ```
 *  class MyActivity: AppCompatActivity() {
 *      private val permissionLauncher = registerForPermissionFlowRequestsResult()
 *
 *      fun askContactPermission() {
 *          permissionLauncher.launch(android.Manifest.permission.READ_CONTACTS)
 *      }
 *  }
 * ```
 *
 * @param requestPermissionsContract A contract specifying permission request and result.
 * @param callback Callback of a permission state change.
 */
@JvmOverloads
fun ComponentActivity.registerForPermissionFlowRequestsResult(
    requestPermissionsContract: RequestPermissionsContract = RequestPermissionsContract(),
    callback: ActivityResultCallback<Map<String, Boolean>> = emptyCallback(),
): ActivityResultLauncher<Array<String>> =
    registerForActivityResult(
        requestPermissionsContract,
        activityResultRegistry,
        callback,
    )

/**
 * Returns a [ActivityResultLauncher] for this Fragment which internally notifies [PermissionFlow]
 * about the state change whenever permission state is changed with this launcher.
 *
 * Usage:
 * ```
 *  class MyFragment: Fragment() {
 *      private val permissionLauncher = registerForPermissionFlowRequestsResult()
 *
 *      fun askContactPermission() {
 *          permissionLauncher.launch(android.Manifest.permission.READ_CONTACTS)
 *      }
 *  }
 * ```
 *
 * @param requestPermissionsContract A contract specifying permission request and result. registry.
 * @param callback Callback of a permission state change.
 */
@JvmOverloads
fun Fragment.registerForPermissionFlowRequestsResult(
    requestPermissionsContract: RequestPermissionsContract = RequestPermissionsContract(),
    callback: ActivityResultCallback<Map<String, Boolean>> = emptyCallback(),
): ActivityResultLauncher<Array<String>> =
    registerForActivityResult(
        requestPermissionsContract,
        callback,
    )

/**
 * Returns a [ActivityResultLauncher] for this Fragment which internally notifies [PermissionFlow]
 * about the state change whenever permission state is changed with this launcher.
 *
 * Usage:
 * ```
 *  class MyFragment: Fragment() {
 *      private val permissionLauncher = registerForPermissionFlowRequestsResult()
 *
 *      fun askContactPermission() {
 *          permissionLauncher.launch(android.Manifest.permission.READ_CONTACTS)
 *      }
 *  }
 * ```
 *
 * @param requestPermissionsContract A contract specifying permission request and result.
 * @param activityResultRegistry Activity result registry. By default it uses Activity's Result
 *   registry.
 * @param callback Callback of a permission state change.
 */
@JvmOverloads
fun Fragment.registerForPermissionFlowRequestsResult(
    requestPermissionsContract: RequestPermissionsContract = RequestPermissionsContract(),
    activityResultRegistry: ActivityResultRegistry,
    callback: ActivityResultCallback<Map<String, Boolean>> = emptyCallback(),
): ActivityResultLauncher<Array<String>> =
    registerForActivityResult(
        requestPermissionsContract,
        activityResultRegistry,
        callback,
    )

private fun <T> emptyCallback() = ActivityResultCallback<T> {}